package com.gw.smscheck.controller.business.positionInfo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gw.smscheck.entity.business.alarm.AlarmEnterArea;
import com.gw.smscheck.entity.business.alarm.AlarmInfo;
import com.gw.smscheck.entity.business.alarm.AlarmLog;
import com.gw.smscheck.entity.business.positionInfo.PositionArea;
import com.gw.smscheck.entity.business.positionInfo.PositionInfo;
import com.gw.smscheck.entity.business.positionInfo.PositionTrajectory;
import com.gw.smscheck.entity.sys.DataDictionary;
import com.gw.smscheck.service.business.alarm.AlarmEnterAreaService;
import com.gw.smscheck.service.business.alarm.AlarmInfoService;
import com.gw.smscheck.service.business.alarm.AlarmLogService;
import com.gw.smscheck.service.business.positionInfo.PositionAreaService;
import com.gw.smscheck.service.business.positionInfo.PositionInfoService;
import com.gw.smscheck.service.business.positionInfo.PositionNowService;
import com.gw.smscheck.service.sys.DataDictionaryService;
import com.gw.smscheck.util.DoubleUtil;
import com.gw.smscheck.util.MapUtil;
import com.gw.smscheck.util.TimeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;


/**
 * 位置数据日志接口
 */
@Api(description="【位置数据日志接口】")
@Controller
@RequestMapping("/positionLogController")
public class PositionLogController {
    @Autowired
    PositionInfoService positionInfoService;

    @Autowired
    PositionNowService positionNowService;

    @Autowired
    PositionAreaService positionAreaService;

    @Autowired
    AlarmLogService alarmLogService;

    @Autowired
    AlarmEnterAreaService alarmEnterAreaService;

    @Autowired
    AlarmInfoService alarmInfoService;

    @Autowired
    DataDictionaryService dataDictionaryService;


    /**
     * 模拟数据统一时间段处理
     * @param positionInfo
     */
    @RequestMapping(value = "/batchWalk", method = { RequestMethod.GET})
    @ApiOperation(value="批量轨迹生成", notes="批量轨迹生成")
    public void batchWalk(PositionInfo positionInfo){
        //设置批处理用户
        //获取用户下一步动作
        String[] userPhoneArr = positionInfo.getPhoneNum().split(",");
        //初始化用户位置数据队列
        Map<String,BlockingQueue<String>>  positiongQueueMap = new HashMap<>();
        //死循环开始按批次处理数据
        while(true){
            String groupName = UUID.randomUUID().toString().replaceAll("-", "");
            for(String phoneNum : userPhoneArr){
                PositionInfo tempPosition = new PositionInfo();
                tempPosition.setPhoneNum(phoneNum);
                tempPosition.setGroupName(groupName);
                //如果为空或为长度为0则刷新map中的队列
                if(positiongQueueMap.get(phoneNum) == null || positiongQueueMap.get(phoneNum).size() == 0){
                    positiongQueueMap.put(phoneNum,initQueue(positiongQueueMap.get(phoneNum),tempPosition));
                }else{
                    //正常处理设置数据，并设置分组字段
                    //添加点
                    addPoint(positiongQueueMap.get(phoneNum).poll(),tempPosition);
                }
            }
            //一组处理完，休息1分钟
            try {
                Thread.sleep(1000*60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }




    @RequestMapping(value = "/walk", method = { RequestMethod.GET})
    @ApiOperation(value="步行轨迹生成", notes="步行轨迹生成")
    public void walk(PositionInfo positionInfo) {
        //队列
        BlockingQueue<String> basket = null;
        basket = initQueue(basket,positionInfo);//一开始先初始化
        while(true){
            if(basket == null || basket.size() == 0){
                //添加数据
                basket = initQueue(basket,positionInfo);
            }else{
                System.out.println(basket.poll());
                //添加点
                addPoint(basket.poll(),positionInfo);
                //告警判断
                //获取当前人的告警类型集合
                //离开指定辖区告警
                try {
                    Thread.sleep(1000*60);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 添加点
     * @param lngLat
     * @param positionInfo
     */
    private void addPoint(String lngLat,PositionInfo positionInfo){
        if(lngLat != null){
            PositionTrajectory newPosition = positionInfoService.getNewByPhone(positionInfo.getPhoneNum());
            //基础数据
            PositionInfo temp = new PositionInfo();
            temp.setPhoneNum(positionInfo.getPhoneNum());
            temp.setGroupName(positionInfo.getGroupName());//设置组别
            temp.setTime(TimeUtil.timeAddMinute(newPosition.getLastTime()));
            //动态生成经纬度
            Double nowLng = Double.parseDouble(lngLat.split(",")[0]);
            Double nowLat = Double.parseDouble(lngLat.split(",")[1]);
            nowLng = DoubleUtil.format(nowLng,6);
            nowLat = DoubleUtil.format(nowLat,6);

            temp.setLng(nowLng);
            temp.setLat(nowLat);
            positionInfoService.add(temp);//添加信令日志记录
            //如果上一个点和当前这个点的位置一致，则修改上一个点的last_time为当前时间点
            //否则新增一条数据
            if(newPosition.getLng().equals(nowLng) && newPosition.getLat().equals(nowLat)){
                System.out.println("update");
                newPosition.setLastTime(temp.getTime());
                newPosition.setLat(nowLat);
                newPosition.setLng(nowLng);
                positionInfoService.updateLastTimeForTrajectory(newPosition);
            }else{
                System.out.println("添加");
                positionInfoService.addTrajectory(temp);
            }
            //添加最新日志，存在即更新，反之插入
            positionNowService.updataInsert(temp);

            //告警验证
//            alarmCheck(temp);



        }
    }


    /**
     * 告警验证
     * @param checkObj
     */
    private void alarmCheck(PositionInfo checkObj) {
        System.out.println("开始验证:"+checkObj.getPhoneNum());
        //获取人员所有告警内容
        List<AlarmInfo> alarmInfoList = alarmInfoService.findByFocusPh(checkObj.getPhoneNum());

        for(AlarmInfo alarmInfo : alarmInfoList){
            //根据类型验证告警
            int alarmType = alarmInfo.getAlarmType();
            switch(alarmType){
                case 6:outAreaCheck(checkObj,alarmInfo);break;
                case 5:inAreaCheck(checkObj,alarmInfo);break;
                case 7:
                    System.out.println("手机关机告警");break;
                case 8:System.out.println("手机脱网告警");break;
                case 9:System.out.println("发呆告警");break;
                case 10:System.out.println("同类聚集告警");break;
            }
        }

    }

    /**
     * 离开辖区告警
     */
    private void outAreaCheck(PositionInfo checkObj,AlarmInfo alarmInfo) {
        System.out.println("离开辖区告警");
        DataDictionary dataDictionary = new DataDictionary();
        dataDictionary.setId(alarmInfo.getAlarmType());
        dataDictionary = dataDictionaryService.getById(dataDictionary);

        //分割出该人员指定的辖区组
        if(alarmInfo!= null && alarmInfo.getIds() != null){
            String[] checkIdArr = alarmInfo.getIds().split(",");
            //循环遍历辖区，验证其是否离开辖区
            for(String areaId : checkIdArr){
                areaId= areaId.trim();
                PositionArea checkArea = positionAreaService.findById(Integer.parseInt(areaId));
                System.out.println("辖区边界："+checkArea.getBoundary());
                System.out.println("验证经纬度："+checkObj.getLng()+","+checkObj.getLat());
                boolean isInArea = MapUtil.isPtInPoly(checkArea.getBoundary(),checkObj.getLng(),checkObj.getLat());
                //如果不在区域内则告警，生成一条告警日志
                if(!isInArea){
                    System.out.println("离开辖区，产生一条告警");
                    AlarmLog alarmLog = new AlarmLog();
                    alarmLog.setAlarmContent("离开"+checkArea.getName());
                    alarmLog.setAlarmName(dataDictionary.getName());
                    alarmLog.setAlarmType(String.valueOf(alarmInfo.getAlarmType()));
                    alarmLog.setUserCode(alarmInfo.getFocusPh());
                    alarmLog.setUserPhone(checkObj.getPhoneNum());
                    alarmLog.setAlarmTime(checkObj.getTime());
                    alarmLog.setIndex(dataDictionary.getIndex());
                    alarmLogService.add(alarmLog);
                }
            }
        }
    }

    /**
     * 进入指定地点告警
     */
    private void inAreaCheck(PositionInfo checkObj,AlarmInfo alarmInfo) {
        System.out.println("离开辖区告警");
        DataDictionary dataDictionary = new DataDictionary();
        dataDictionary.setId(alarmInfo.getAlarmType());
        dataDictionary = dataDictionaryService.getById(dataDictionary);
        //获取所有区域
        //循环遍历辖区，验证其是否离开辖区
        //分割出该人员指定的辖区组
        if(alarmInfo!= null && alarmInfo.getIds() != null){
            String[] checkIdArr = alarmInfo.getIds().split(",");
            for(String areaId : checkIdArr){
                AlarmEnterArea checkArea = alarmEnterAreaService.findById(Integer.parseInt(areaId));
                boolean isInArea = MapUtil.isPtInPoly(checkArea.getBoundary(),checkObj.getLng(),checkObj.getLat());
                //如果不在区域内则告警，生成一条告警日志
                if(isInArea){
                    System.out.println("进入指定地点，产生一条告警");
                    AlarmLog alarmLog = new AlarmLog();
                    alarmLog.setAlarmContent("进入"+checkArea.getName());
                    alarmLog.setAlarmName(dataDictionary.getName());
                    alarmLog.setAlarmType(String.valueOf(alarmInfo.getAlarmType()));
                    alarmLog.setUserCode(alarmInfo.getFocusPh());
                    alarmLog.setUserPhone(checkObj.getPhoneNum());
                    alarmLog.setAlarmTime(checkObj.getTime());
                    alarmLog.setIndex(dataDictionary.getIndex());
                    alarmLogService.add(alarmLog);
                }else{
                    System.out.println("未进入区域");
                }
            }
        }
    }


    /**
     * 队列为空或长度为0是重新初始化数据
     * @param basket
     * @param positionInfo
     */
    private BlockingQueue<String> initQueue(BlockingQueue<String> basket, PositionInfo positionInfo) {
        //获取上一条数据
        PositionTrajectory newPosition = positionInfoService.getNewByPhone(positionInfo.getPhoneNum());

        //初始位置打印
        System.out.println("初始位置："+newPosition.getLng()+"-"+newPosition.getLat());
        //根据初始点生成下一个随机点
        Double nextLng = DoubleUtil.getRandom(newPosition.getLng(),50,30,0.001);
        Double nextLat = DoubleUtil.getRandom(newPosition.getLat(),50,30,0.001);

        System.out.println("随机位置："+nextLng+"-"+nextLat);
        //调用接口生成路线轨迹点
        String result = "";
        String url = "http://api.map.baidu.com/direction/v1?mode=walking&region=贵阳&origin="
                +newPosition.getLat()+","+newPosition.getLng()
                +"&destination="
                +nextLat+","+nextLng
                +"&output=json&ak=1XjLLEhZhQNUzd93EjU5nOGQ";
        System.out.println(url);
        // 获取请求连接
        Connection con = Jsoup.connect(url);
        // 请求头设置，特别是cookie设置
        con.header("Accept", "text/html, application/xhtml+xml, */*");
        con.header("Content-Type", "application/x-www-form-urlencoded");
        con.header("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0))");
        con.header("Cookie", null);
        con.followRedirects(true);
        Connection.Response resp;
        String body = "";
        try {
            resp = con.method(Connection.Method.GET).execute();
            body = resp.body();
            JSONObject jsonObj = JSONObject.parseObject(body);
            JSONObject resultObj = jsonObj.getJSONObject("result");
            JSONArray routesArr = resultObj.getJSONArray("routes");
            if(routesArr.size() > 0){
                JSONObject routeObj = routesArr.getJSONObject(0);
                JSONArray stepsArr = routeObj.getJSONArray("steps");
                if(stepsArr.size() > 0){
                    basket = new LinkedBlockingDeque<String>();
                    //添加头
                    basket.add(newPosition.getLng()+","+newPosition.getLat());
                    for(int i = 0 ; i<stepsArr.size();i++){
                        JSONObject stepObj = stepsArr.getJSONObject(i);
                        String pathStr = stepObj.getString("path");
                        System.out.println(pathStr);
                        String[] lnglatArr = pathStr.split(";");
                        for(String str : lnglatArr){
                            basket.add(str);
                        }
                    }
                    //添加尾
                    basket.add(nextLng+","+nextLat);
                    System.out.println("队列的长度"+basket.size());
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        return basket;
    }

}
